package main

import (
	"fmt"
)

type MyStruct struct {
	value string
}

func (s MyStruct) show() {
	fmt.Println(s.value)
}

type MyStruct2 MyStruct

func (s MyStruct2) show1() {
    //MyStruct2 can use its underlying type's field directly
    fmt.Println(s.value)
}

func (s MyStruct2) show2() {
	//can't use MyStruct method
	// s.show()

	//MyStruct2 instance can be converted to MyStruct
	//because they have the same underlying type `struct{value string}
	s1 := MyStruct(s)
	s1.show()
}

type MyStruct3 struct {
	value string
}

type MyStruct4 struct {
	name string
}

type MyString string

type MyStruct5 struct {
	value MyString
}

func main() {
	s1 := MyStruct{"s1"}
	s2 := MyStruct2{"s2"}

	s1.show()
	s2.show1()
	s2.show2()

    //MyStruct instance can be explicitly converted to MyStruct3 and vice versa
    //because the both have the same underlying type struct{value string}
    var s3 MyStruct3 = MyStruct3(s1)
    fmt.Println(s3.value)

    //MyStruct instance can NOT be converted to MyStruct4 and vice versa
    //because MyStruct's underlying type is struct{value string}, MyStruct4's underlying type is struct{name string}, the field names of their underlying type are different, so their underlying typs are deemed different
    // var s4 MyStruct4 = MyStruct4(s1)

    //MyStruct instance can NOT be converted to MyStruct5 and vice versa
    //because their underlying types are NOT the same, similar to MyStruct4, the only difference is that the field names of underlying type are the same ,but the types of the field are not, even if string is the source of MyString. underlying type tracing stops at struct{...}, NOT continue to trace inside the struct
    var s5 MyStruct5 = MyStruct5(s1)
}
